package com.hanserwei.han_picture.service.seviceImpl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hanserwei.han_picture.domain.entity.po.Space;
import com.hanserwei.han_picture.domain.entity.po.SpaceUser;
import com.hanserwei.han_picture.domain.entity.po.User;
import com.hanserwei.han_picture.domain.entity.vo.SpaceUserVO;
import com.hanserwei.han_picture.domain.entity.vo.SpaceVO;
import com.hanserwei.han_picture.domain.entity.vo.UserVO;
import com.hanserwei.han_picture.domain.exception.ApiException;
import com.hanserwei.han_picture.domain.request.spaceuser.SpaceUserAddRequest;
import com.hanserwei.han_picture.domain.request.spaceuser.SpaceUserQueryRequest;
import com.hanserwei.han_picture.enums.ResponseCodeEnum;
import com.hanserwei.han_picture.enums.SpaceUserRoleEnum;
import com.hanserwei.han_picture.mapper.SpaceUserMapper;
import com.hanserwei.han_picture.service.SpaceService;
import com.hanserwei.han_picture.service.SpaceUserService;
import com.hanserwei.han_picture.service.UserService;
import com.hanserwei.han_picture.utils.ThrowUtils;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor
public class SpaceUserServiceImpl extends ServiceImpl<SpaceUserMapper, SpaceUser> implements SpaceUserService {

    private final UserService userService;

    @Resource
    @Lazy
    private SpaceService spaceService;


    /**
     * 添加空间成员
     *
     * @param request 请求参数
     */
    @Override
    public boolean addSpaceUser(SpaceUserAddRequest request) {
        ThrowUtils.throwIf(request == null, ResponseCodeEnum.INVALID_PARAMETER, "参数错误！");
        SpaceUser spaceUser = new SpaceUser();
        BeanUtils.copyProperties(request, spaceUser);
        validSpaceUser(spaceUser, true);
        boolean saved = this.save(spaceUser);
        ThrowUtils.throwIf(!saved, ResponseCodeEnum.INVALID_PARAMETER, "添加空间成员失败！");
        return true;
    }

    /**
     * 获取空间成员包装类
     *
     * @param spaceUser spaceUser
     * @return spaceUserVO
     */
    @Override
    public SpaceUserVO getSpaceUserVO(SpaceUser spaceUser) {
        // 转换为VO类
        SpaceUserVO spaceUserVO = SpaceUserVO.objToVo(spaceUser);
        // 关联查询用户信息
        Long userId = spaceUser.getUserId();
        if (userId != null && userId > 0) {
            User user = userService.getById(userId);
            UserVO userVO = userService.getUserVO(user);
            spaceUserVO.setUserVO(userVO);
        }
        // 关联查询空间信息
        Long spaceId = spaceUser.getSpaceId();
        if (spaceId != null && spaceId > 0) {
            Space space = spaceService.getById(spaceId);
            SpaceVO spaceVO = spaceService.getSpaceVO(space);
            spaceUserVO.setSpaceVO(spaceVO);
        }
        return spaceUserVO;
    }

    /**
     * 获取空间成员列表包装类
     *
     * @param spaceUserList spaceUserList
     * @return spaceUserVOList
     */
    @Override
    public List<SpaceUserVO> getSpaceUserVOList(List<SpaceUser> spaceUserList) {
        if (CollUtil.isEmpty(spaceUserList)) {
            return Collections.emptyList();
        }

        // 1. 批量获取关联数据所需要的ID集合
        Set<Long> userIdSet = spaceUserList.stream()
                .map(SpaceUser::getUserId)
                .collect(Collectors.toSet());
        Set<Long> spaceIdSet = spaceUserList.stream()
                .map(SpaceUser::getSpaceId)
                .collect(Collectors.toSet());

        // 2. 批量查询，并转换为ID为key的Map，方便后续查找
        // 使用 Function.identity() 表示值就是对象本身
        Map<Long, User> userMap = userService.listByIds(userIdSet).stream()
                .collect(Collectors.toMap(User::getId, Function.identity()));
        Map<Long, Space> spaceMap = spaceService.listByIds(spaceIdSet).stream()
                .collect(Collectors.toMap(Space::getId, Function.identity()));

        // 3. 转换VO并填充关联数据
        return spaceUserList.stream().map(spaceUser -> {
            // 基础转换
            SpaceUserVO spaceUserVO = SpaceUserVO.objToVo(spaceUser);

            // 填充用户数据
            User user = userMap.get(spaceUser.getUserId());
            spaceUserVO.setUserVO(userService.getUserVO(user));

            // 填充空间数据
            Space space = spaceMap.get(spaceUser.getSpaceId());
            spaceUserVO.setSpaceVO(spaceService.spaceToSpaceVO(space));

            return spaceUserVO;
        }).toList();
    }

    /**
     * 校验空间成员对象
     *
     * @param spaceUser spaceUser
     * @param add       是否是创建公共空间时校验
     */
    @Override
    public void validSpaceUser(SpaceUser spaceUser, boolean add) {
        ThrowUtils.throwIf(spaceUser == null, ResponseCodeEnum.INVALID_PARAMETER, "参数错误！");
        Long userId = spaceUser.getUserId();
        Long spaceId = spaceUser.getSpaceId();
        if (BooleanUtil.isTrue(add)) {
            // 创建公共空间, 需要添加用户 id 与 空间 id
            ThrowUtils.throwIf(ObjUtil.hasEmpty(userId, spaceId), ResponseCodeEnum.INVALID_PARAMETER, "参数错误！");
            User user = userService.getById(userId);
            ThrowUtils.throwIf(user == null, ResponseCodeEnum.INVALID_PARAMETER, "用户不存在！");
            Space space = spaceService.getById(spaceId);
            ThrowUtils.throwIf(space == null, ResponseCodeEnum.INVALID_PARAMETER, "空间不存在！");
        }
        // 编辑空间，检验空间角色
        String spaceRole = spaceUser.getSpaceRole();
        SpaceUserRoleEnum spaceUserRoleEnum = SpaceUserRoleEnum.getEnumByValue(spaceRole);
        if (spaceRole != null && spaceUserRoleEnum == null) {
            throw new ApiException(ResponseCodeEnum.INVALID_PARAMETER, "空间角色错误！");
        }
    }

    /**
     * 封装查询条件
     *
     * @param request 查询参数
     * @return 查询条件
     */
    @Override
    public QueryWrapper<SpaceUser> getQueryWrapper(SpaceUserQueryRequest request) {
        QueryWrapper<SpaceUser> queryWrapper = new QueryWrapper<>();
        if (ObjUtil.isNull(request)) {
            return queryWrapper;
        }
        // 封装查询条件
        Long id = request.getId();
        Long spaceId = request.getSpaceId();
        Long userId = request.getUserId();
        String spaceRole = request.getSpaceRole();
        queryWrapper.eq(StrUtil.isNotEmpty(spaceRole), "space_role", spaceRole);
        queryWrapper.eq(id != null && id > 0, "id", id);
        queryWrapper.eq(spaceId != null && spaceId > 0, "space_id", spaceId);
        queryWrapper.eq(userId != null && userId > 0, "user_id", userId);
        return queryWrapper;
    }
}
